Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

waffle mark 🧇 #2040

Merged
merged 23 commits into from
Aug 4, 2024
Merged

waffle mark 🧇 #2040

merged 23 commits into from
Aug 4, 2024

Conversation

mbostock
Copy link
Member

@mbostock mbostock commented Mar 27, 2024

Fixes #2029.

  • waffleX
  • waffleY
  • Rounded corners (rx, ry)
  • Automatic row/column size determination
  • Fractional cell rendering
  • Configurable units
  • Configurable gap
  • Fix patterns in test snapshots
  • Fix the r option; don’t allow asymmetric corner rounding
  • Fix orientation of partial rows with negative values
  • Fix rendering stroke glitch with partial cells
  • Handle constant fill and stroke better
  • Consolidate and optimize waffle rendering
  • Documentation
  • Tests

@mbostock
Copy link
Member Author

mbostock commented Aug 1, 2024

Current status:

Screenshot 2024-08-01 at 11 43 54 AM

I’m now computing the number of waffle cell columns correctly, and rendering them as a pattern. But I need to replace the rect elements generated by BarY with a path element so that the top & bottom cells aren’t truncated (unless there’s a fractional value).

@mbostock
Copy link
Member Author

mbostock commented Aug 1, 2024

Now with fractional cell rendering!

Screenshot 2024-08-01 at 1 15 25 PM

@mbostock mbostock marked this pull request as ready for review August 3, 2024 00:29
@mbostock mbostock requested a review from Fil August 3, 2024 00:29
@mbostock mbostock changed the title waffle waffle mark 🧇 Aug 3, 2024
@mbostock
Copy link
Member Author

mbostock commented Aug 3, 2024

Whew! 😅 That was a lot of work but I’m pretty happy with how this turned out.

@mbostock
Copy link
Member Author

mbostock commented Aug 4, 2024

localhost_5173_plot_marks_waffle

@Fil
Copy link
Contributor

Fil commented Aug 4, 2024

I was wondering how to use this for ISOTYPE charts, and it appears that it's possible to use the render transform to edit the patterns’ contents:

render: (index, scales, values, dimensions, context, next) => {
  const g = next(index, scales, values, dimensions, context);
  const pattern = d3.select(g).selectAll("pattern");
  pattern.selectAll("rect").remove();
  pattern.append("text").attr("x", 10).attr("y", 15).text("🚀");
  return g;
}
Capture d’écran 2024-08-04 à 12 18 39

This gives two ideas for future enhancements:

  • extend the mark to accept a symbol option, or
  • extend the mark to accept a pattern option

The rendered pattern might also be easier to manipulate if it was centered on the origin with a viewBox rather than extending from it (in that case, the values for x and y above would essentially be zero).

@@ -62,10 +62,11 @@ function waffleRender(y) {
     const basePattern = document.createElementNS(namespaces.svg, "pattern");
     basePattern.setAttribute("width", cellsize);
     basePattern.setAttribute("height", cellsize);
+    basePattern.setAttribute("viewBox", [-cellsize / 2, -cellsize / 2, cellsize, cellsize]);
     basePattern.setAttribute("patternUnits", "userSpaceOnUse");
     const basePatternRect = basePattern.appendChild(document.createElementNS(namespaces.svg, "rect"));
-    basePatternRect.setAttribute("x", gap / 2);
-    basePatternRect.setAttribute("y", gap / 2);
+    basePatternRect.setAttribute("x", (gap - cellsize) / 2);
+    basePatternRect.setAttribute("y", (gap - cellsize) / 2);
     basePatternRect.setAttribute("width", cellsize - gap);
     basePatternRect.setAttribute("height", cellsize - gap);
     if (rx != null) basePatternRect.setAttribute("rx", rx);

src/marks/waffle.js Outdated Show resolved Hide resolved
@Fil
Copy link
Contributor

Fil commented Aug 4, 2024

It makes total sense that the number of rows/columns is completely automatic and not configurable, but it might be useful to call this out explicitly in the documentation? And give hints on how to alter the number of rows and columns (such as layering several marks like in the Syrian teenagers example, changing the chart's aspect ratio, using scale insets, etc).

@Fil
Copy link
Contributor

Fil commented Aug 4, 2024

It might be nice in the future to allow a configurable orientation (e.g. filling rows from the left instead of from the right). Not a blocker at all, I'm not even sure I would use it.

@mbostock
Copy link
Member Author

mbostock commented Aug 4, 2024

It makes total sense that the number of rows/columns is completely automatic and not configurable, but it might be useful to call this out explicitly in the documentation?

That’s already called out here:

The waffle mark automatically determines the appropriate number of cells per row or per column (depending on orientation) such that the cells are square, don’t overlap, and are consistent with position scales.

It would also be very easy to expose this as an option. In fact I had it as an option in the past. But it was a footgun: if you hard-code the value it’s easy to produce overlapping waffles. In practice, what I want is to guarantee that the rows/columns is either a factor or a multiple of the corresponding position scale. The waffle mark doesn’t have that information easily available at render time, though (since the axis could be rendered after the waffle, or there could be multiple axes)… maybe an option to limit it to a power of ten times 1, 2, 5? Anyway.

The number of rows/columns is also heavily affected by the values, so I’m not sure I have much useful hints. Maybe just, if you have narrower bands, you have fewer cells per row/column? Setting padding on the ordinal scale for example.

@mbostock
Copy link
Member Author

mbostock commented Aug 4, 2024

It might be nice in the future to allow a configurable orientation (e.g. filling rows from the left instead of from the right).

Sure… though I’m skeptical of adding such an obscure feature unless someone can explain why it’s worth adding. You could always do it with a custom mark or render transform.

@mbostock
Copy link
Member Author

mbostock commented Aug 4, 2024

The ISOTYPE chart idea is interesting, but I’m not sure how well the waffle would work for that since often the glyphs are non-square and can vary in size across series. There’s no meaningful position encoding in an ISOTYPE chart; you’re just responsible for counting glyphs to perceive the encoded value.

image

But for sure there are more extensions we could do here than square/rounded squares for the pattern! I don’t think we should implement these now, with the possible exception of non-square aspect ratios as previously mentioned.

@mbostock mbostock enabled auto-merge (squash) August 4, 2024 19:30
Copy link
Contributor

@Fil Fil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧇 🧇 🧇

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Waffle mark
2 participants